/*
@hehung
2023-2-8
转载请注明出处，版权由@hehung所有
email: 1398660197@qq.com
wechat: hehung95
*/

#include "hal_data.h"
#include "app_key.h"
#include "app_led.h"


#define KEY_DEBUG
#undef KEY_DEBUG

#ifdef KEY_DEBUG
#include <stdio.h>
#endif


// Total number of keys
#define KEY_TOTAL_NUM              (2U)
#define KEY_1                      (0U)
#define KEY_2                      (1U)

// Key press/release status
#define KEY_PRESSED                (1U)
#define KEY_RELEASED               (0U)

#define KEY_FILTER_THD             (4U)    /* 40ms */

/* defined the KEY1 pin */
#define KEY1_PIN                   (0U)
/* defined the KEY3 pin */
#define KEY2_PIN                   (1U)

// Key pin level: low or high
#define PIN_LOW                    (BSP_IO_LEVEL_LOW)
#define PIN_HIGH                   (BSP_IO_LEVEL_HIGH)


// type for key status
typedef struct
{
    uint8_t   key_pin;
    uint8_t   key_val;
    uint8_t   key_status;
    uint8_t   key_pre_status;
    uint8_t   key_pending_cnt;
} s_KeyCtrlType;


// key conrol status
static s_KeyCtrlType key_ctrl[KEY_TOTAL_NUM] =
{
    {
        .key_pin = KEY1_PIN,
        .key_val = PIN_LOW,
        .key_status = KEY_RELEASED,
        .key_pre_status = KEY_RELEASED,
        .key_pending_cnt = 0U
    },
    {
        .key_pin = KEY2_PIN,
        .key_val = PIN_LOW,
        .key_status = KEY_RELEASED,
        .key_pre_status = KEY_RELEASED,
        .key_pending_cnt = 0U
    }
};


static uint8_t Key_ReadPinLevel(uint8_t key_num);
static void Key_StatusJudge(uint8_t key_num);

// used for read pin level
static uint8_t Key_ReadPinLevel(uint8_t key_num)
{
    bsp_io_port_pin_t key_pin[KEY_TOTAL_NUM] = 
    {
        BSP_IO_PORT_00_PIN_05,
        BSP_IO_PORT_00_PIN_06
    };
    bsp_io_level_t pin_level;
    uint8_t ret_pin_l = PIN_LOW;

    if (FSP_SUCCESS ==  R_IOPORT_PinRead(&g_ioport_ctrl, key_pin[key_num], &pin_level))
    {
        if (BSP_IO_LEVEL_HIGH == pin_level)
        {
            ret_pin_l = PIN_HIGH;
        }
    }

    return ret_pin_l;
}

// Judge the key presss status
static void Key_StatusJudge(uint8_t key_num)
{
    if ((KEY_PRESSED == key_ctrl[key_num].key_status) &&
        (KEY_RELEASED == key_ctrl[key_num].key_pre_status))
    {
        // key pressed
        switch (key_num)
        {
            case KEY_1: Led_ChangeStatus(0); break;
            case KEY_2: Led_ChangeStatus(1); break;
            default: break;
        }
    }
    else if ((KEY_RELEASED == key_ctrl[key_num].key_status) &&
            (KEY_PRESSED == key_ctrl[key_num].key_pre_status))
    {
        // key released
    }
    else if ((KEY_PRESSED == key_ctrl[key_num].key_status) &&
            (KEY_PRESSED == key_ctrl[key_num].key_pre_status))
    {
       // key keep press
    }
    else
    {
        // key keep release
    }
}

// main function for key sampling and status judge
void Key_RunningEntry(void)
{
    uint8_t i;

    for (i = 0; i < KEY_TOTAL_NUM; i++)
    {
        key_ctrl[i].key_val = Key_ReadPinLevel(key_ctrl[i].key_pin);
#ifdef KEY_DEBUG
        printf("Key%d: %d, gpio:%d ", i, key_ctrl[i].key_val, key_ctrl[i].key_pin);
#endif
        if (key_ctrl[i].key_val == PIN_LOW)
        {
            if (key_ctrl[i].key_pending_cnt < KEY_FILTER_THD)
                key_ctrl[i].key_pending_cnt ++;
        }
        else
        {
            if (key_ctrl[i].key_pending_cnt > 0U)
                key_ctrl[i].key_pending_cnt --;
        }

        /* Filter */
        if (key_ctrl[i].key_pending_cnt >= KEY_FILTER_THD)
        {
            key_ctrl[i].key_status = KEY_PRESSED;
        }
        else if (key_ctrl[i].key_pending_cnt == 0U)
        {
            key_ctrl[i].key_status = KEY_RELEASED;
        }
		
		Key_StatusJudge(i);

        key_ctrl[i].key_pre_status = key_ctrl[i].key_status;
    }
#ifdef KEY_DEBUG
    printf("\n");
#endif
}

